import json
import re

from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import Paginator, EmptyPage
from django.db import DatabaseError
from django.http import HttpResponse, HttpResponseForbidden, HttpResponseNotFound
from django.shortcuts import render, redirect
from django.http import JsonResponse

from orders.models import OrderInfo
from users import constants
from utils.response_code import RETCODE

# Create your views here.
from django.urls import reverse
from django.views import View

from users.models import User, Address


class Regist(View):
    def get(self, request):
        return render(request, 'register.html')

    def post(self, request):
        # 取得用户传递过来的信息
        form_dict = request.POST
        username = form_dict.get('username')
        password = form_dict.get('password')
        password2 = form_dict.get('password2')
        mobile = form_dict.get('mobile')
        allow = form_dict.get('allow')

        # 校验参数
        if not all([username, password, password2, mobile, allow]):
            return render(request, 'register.html', {'register_errmsg': '缺少必传参数'})

        if password != password2:
            return render(request, 'register.html', {'register_errmsg': '两次输入的密码不一致'})

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return render(request, 'register.html', {'register_errmsg': '手机号格式错误'})

        if allow != 'on':
            return render(request, 'register.html', {'register_errmsg': '请同意用户协议'})

        try:
            # 注册成功的用户对象
            user = User.objects.create_user(username=username, mobile=mobile, password=password)
        except DatabaseError as e:
            return render(request, 'register.html', {'register_errmsg': '注册失败: {}'.format(str(e))})

        login(request, user)  # 登入用户，实现状态保持
        # 响应登录结果:重定向到首页
        response = redirect(reverse('contents:index'))
        # 为了实现在首页右上角展示用户信息，我们需要将用户名缓存到cookie中
        response.set_cookie('username', user.username, max_age=3600 * 24 * 14)
        return response


class UsernameCountView(View):
    # """判断用户名是否重复注册"""
    def get(self, request, username):
        count = User.objects.filter(username=username).count()
        return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'count': count})


class MoblieCountView(View):
    def get(self, request, mobile):
        count = User.objects.filter(mobile=mobile).count()
        print("mobile count:", count)
        return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', "count": count})


class LoginView(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        # 接收参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        remembered = request.POST.get('remembered')
        # django框架 封装authenticate方法，
        user = authenticate(username=username, password=password)
        if user is None:
            return render(request, 'login.html', {'account_errmsg': '账号或密码错误'})

        login(request, user)
        if remembered != 'on':
            # 实现状态保持 没有记住用户：浏览器会话结束就过期
            request.session.set_expiry(0)
        else:
            request.session.set_expiry(None)
        # 记住用户：None表示两周后过期，在settings.py中可以设置SESSION_COOKIE_AGE来配置全局的过期时间。默认是2周的时间
        # 登录成功后 看跳转到哪个页面   是回到主页面还是回到next保存的页面
        next = request.GET.get('next')
        # 先取出next
        if next:
            response = redirect(next)
        # 重定向到next
        else:
            response = redirect(reverse('contents:index'))
        print('loginView', type(response))
        # # 为了实现在首页右上角展示用户信息，我们需要将用户名缓存到cookie中
        response.set_cookie('username', user.username, max_age=3600 * 24 * 14)
        return response
        # return redirect(reverse('contents:index'))  # 响应登录结果


class LogoutView(View):
    def get(self, request):
        # 1.删除session（清除状态保存信息）
        logout(request)
        # 2.删除cookie用户名
        response = redirect(reverse("contents:index"))
        response.delete_cookie("username")
        return response


class UserInfoView(LoginRequiredMixin, View):
    def get(self, request):
        # 返回用户中心 同步用户名和手机号
        context = {
            'username': request.user.username,
            'mobile': request.user.mobile,
        }
        return render(request, 'user_center_info.html', context=context)


class UserOrderInfoView(View):
    def get(self, request, page_num):
        """提供我的订单页面"""
        user = request.user
        # 查询订单
        orders = user.orderinfo_set.all().order_by("-create_time")
        # 遍历所有订单
        for order in orders:
            # 绑定订单状态
            order.status_name = OrderInfo.ORDER_STATUS_CHOICES[order.status - 1][1]
            # 绑定支付方式
            order.pay_method_name = OrderInfo.PAY_METHOD_CHOICES[order.pay_method - 1][1]
            order.sku_list = []
            # 查询订单商品
            order_goods = order.skus.all()
            # 遍历订单商品
            for order_good in order_goods:
                sku = order_good.sku
                sku.count = order_good.count
                sku.amount = sku.price * sku.count
                order.sku_list.append(sku)
        # 分页
        page_num = int(page_num)
        try:
            paginator = Paginator(orders, constants.ORDERS_LIST_LIMIT)
            page_orders = paginator.page(page_num)
            total_page = paginator.num_pages
        except EmptyPage:
            return HttpResponseNotFound('订单不存在')

        context = {
            "page_orders": page_orders,
            'total_page': total_page,
            'page_num': page_num,
        }
        return render(request, "user_center_order.html", context)


class AddressView(LoginRequiredMixin, View):
    """展示地址"""

    def get(self, request):
        """提供收货地址界面"""
        login_user = request.user  # 获取当前登录用户对象
        addresses = Address.objects.filter(user=login_user, is_deleted=False)
        address_list = []  # 将用户地址模型列表转字典列表
        for address in addresses:
            address_dict = {
                "id": address.id, "title": address.title,
                "receiver": address.receiver, "city": address.city.name,
                "province": address.province.name, "place": address.place,
                "district": address.district.name, "tel": address.tel,
                "mobile": address.mobile, "email": address.email
            }
            address_list.append(address_dict)
        context = {
            'default_address_id': login_user.default_address_id or '0',
            'addresses': address_list
        }
        return render(request, 'user_center_site.html', context)


class AddressCreateView(LoginRequiredMixin, View):
    """新增地址"""

    def post(self, request):
        count = request.user.addresses.filter(is_deleted__exact=False).count()
        if count >= constants.USER_ADDRESS_COUNTS_LIMIT:
            return JsonResponse({"code": RETCODE.THROTTLINGERR, 'errmsg': "超出用户地址上限"})
        # 接收参数
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')
        # 校验参数
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return HttpResponseForbidden('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseForbidden('参数mobile有误')
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return HttpResponseForbidden('参数tel有误')
        if email:
            if not re.match(r'^[a-z0-9][\w\\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1, 2}$', email):
                return HttpResponseForbidden('参数email有误')
        # 保存用户传入的地址信息
        try:
            address = Address.objects.create(
                user=request.user, title=receiver, receiver=receiver,
                province_id=province_id, place=place, tel=tel,
                city_id=city_id, district_id=district_id,
                mobile=mobile, email=email
            )
            # 设置默认地址
            if not request.user.default_address:
                request.user.default_address = address
                request.user.save()
        except Exception as e:
            return JsonResponse({'code': RETCODE.DBERR, 'errmsg': '新增地址失败'})
        # 新增地址成功，将新增的地址响应给前端实现局部刷新 构造新增地址字典数据

        address_dict = {
            "id": address.id, "title": address.title,
            "receiver": address.receiver, "province": address.province.name,
            "city": address.city.name, "district": address.district.name,
            "place": address.place, "mobile": address.mobile,
            "tel": address.tel, "email": address.email
        }
        # 响应新增地址结果：需要将新增的地址返回给前端渲染
        return JsonResponse({'code': RETCODE.OK, 'errmsg': '新增地址成功', 'address': address_dict})


class DefaultAddressView(LoginRequiredMixin, View):
    """设置默认地址"""

    def put(self, request, address_id):
        """设置默认地址"""
        try:
            address = Address.objects.get(id=address_id)  # 接收参数,查询地址
            request.user.default_address = address  # 设置地址为默认地址
            request.user.save()
        except Exception as e:
            return JsonResponse({'code': RETCODE.DBERR, 'errmsg': '设置默认地址失败'})
            # 响应设置默认地址结果
        return JsonResponse({'code': RETCODE.OK, 'errmsg': '设置默认地址成功'})
